/**
 * @description mention plugin
 * @author Ling
 */

import { DomEditor, IDomEditor } from '@wangeditor/editor';

import { IExtendConfig } from './interface';
import { insertMention } from './insertMention';

function getMentionConfig(editor: IDomEditor) {
  const { EXTEND_CONF } = editor.getConfig();
  const { mentionConfig } = EXTEND_CONF as IExtendConfig;
  return mentionConfig;
}

function withMention<T extends IDomEditor>(editor: T) {
  const { insertText, isInline, isVoid } = editor;
  const newEditor = editor;

  // 重写 insertText
  newEditor.insertText = (t) => {
    // console.log('0-选中的字符-insertText');
    // 选过选中了 void 元素
    const elems = DomEditor.getSelectedElems(newEditor);
    // console.log('选中的元素', elems);
    const isSelectedVoidElem = elems.some((elem) => newEditor.isVoid(elem));
    // console.warn('选中了 void 元素，不能插入文本', isSelectedVoidElem);

    if (isSelectedVoidElem) {
      insertText(t);
      return;
    }

    // mention 相关配置
    const { showTopicModal, hideTopicModal, showAtModal, hideAtModal } = getMentionConfig(newEditor);

    if (t === '#') {
      setTimeout(() => {
        // 这里需要走判断逻辑，如果当前光标前30个字符包含#，则不展示modal
        // 同时将光标前30个字符中#之间的内容提取出来，变成话题插入，同时删除这个几个字【计算需要子的长度】
        // 如果前30个字不包含#，则走正常逻辑，弹出model
        // 获取光标点击的位置

        // 获取最后一个节点的text文本
        const lastNode = elems[0].children[elems[0].children.length - 1];
        if (lastNode == null) {
          return;
        }
        const lastNodeText = lastNode.text;

        // 如果获取到的#后面的内容小于30个字，从最后向前截取到第一个#，不走弹出model的逻辑
        // 如果获取到的#后面的内容大于30个字，则不做特殊处理，直接走弹出model的逻辑

        // 检查 lastNode 中是否包含 #
        if (lastNodeText.includes('#')) {
          // 查找最后一个 # 的位置
          const lastHashIndex = lastNodeText.lastIndexOf('#');
          // 获取 # 之后的子字符串
          const hashSuffix = lastNodeText.slice(lastHashIndex);
          // 获取光标的位置
          let selection = editor.selection;
          if (!selection) {
            return;
          }

          // 判断 # 后面的字符串长度
          // 包括#本身，所以是31
          if (hashSuffix.length <= 31 && hashSuffix.length > 1) {
            // 需要触发选中和删除
            let selection = editor.selection;
            if (!selection) {
              return;
            }

            let newSelection = {
              anchor: selection.anchor,
              focus: {
                path: selection.focus.path,
                offset: selection.focus.offset - hashSuffix.length - 1,
              },
            };
            editor.select(newSelection);
            insertText(' ');
            // 插入话题的方法
            // 将获取的名称前面的#去掉
            const hashName = hashSuffix.replace(/^#/, '');


            const topicLink = `/topic?name=${hashName}`;
            const topicName = `#${hashName}#`;
            const topicTarget = '_topic';
            insertMention(editor, topicName as string, topicLink as string, topicTarget, 'keyboard');
            // 清空选择
            editor.selection = null;
            return;
          }
        }

        // 展示 modal （异步，以便准确获取光标位置）
        if (showTopicModal) showTopicModal('keyboard', newEditor);

        // 监听，隐藏 modal（异步，等待 modal 渲染后再监听）
        setTimeout(() => {
          function _hide() {
            if (hideTopicModal) hideTopicModal(newEditor);
          }
          newEditor.once('fullScreen', _hide);
          newEditor.once('unFullScreen', _hide);
          newEditor.once('scroll', _hide);
          newEditor.once('modalOrPanelShow', _hide);
          newEditor.once('modalOrPanelHide', _hide);

          function hideOnChange() {
            if (newEditor.selection != null) {
              _hide();
              newEditor.off('change', hideOnChange); // 及时解绑
            }
          }
          newEditor.on('change', hideOnChange);
        });
      });
    }

    if (t === '@') {
      setTimeout(() => {
        // 展示 modal （异步，以便准确获取光标位置）
        if (showAtModal) showAtModal('keyboard', newEditor);

        // 监听，隐藏 modal（异步，等待 modal 渲染后再监听）
        setTimeout(() => {
          function _hide() {
            if (hideAtModal) hideAtModal(newEditor);
          }
          newEditor.once('fullScreen', _hide);
          newEditor.once('unFullScreen', _hide);
          newEditor.once('scroll', _hide);
          newEditor.once('modalOrPanelShow', _hide);
          newEditor.once('modalOrPanelHide', _hide);

          function hideOnChange() {
            if (newEditor.selection != null) {
              _hide();
              newEditor.off('change', hideOnChange); // 及时解绑
            }
          }
          newEditor.on('change', hideOnChange);
        });
      });
    }
    // 非 '@' 则执行默认行为
    insertText(t);
  };

  // 重写 isInline
  newEditor.isInline = (elem) => {
    const type = DomEditor.getNodeType(elem);
    if (type === 'mention') {
      return true;
    }

    return isInline(elem);
  };

  // 重写 isVoid
  newEditor.isVoid = (elem) => {
    const type = DomEditor.getNodeType(elem);
    if (type === 'mention') {
      return true;
    }

    return isVoid(elem);
  };

  return newEditor;
}

export default withMention;
